package org.iabako.client.ui.form.business.sale;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import org.iabako.client.tools.DefaultSuggestHandler;
import org.iabako.client.tools.IabakoAsyncCallback;
import org.iabako.client.ui.form.business.SearchForm;
import org.iabako.client.ui.form.business.util.SearchActionHandler;
import org.iabako.client.ui.layout.field.CheckboxBoolean;
import org.iabako.client.ui.layout.field.InputTextDate;
import org.iabako.client.ui.layout.field.SelectList;
import org.iabako.client.ui.layout.widget.customField.CustomFieldsInstance;
import org.iabako.client.ui.layout.widget.datatable.DataTable;
import org.iabako.client.ui.layout.widget.tooltip.TooltipListener;
import org.iabako.shared.entity.business.Product;
import org.iabako.shared.entity.business.Service;
import org.iabako.shared.entity.enumeration.FinancialStatusSale;
import org.iabako.shared.iservice.business.ProductServiceAsync;
import org.iabako.shared.iservice.business.SaleServiceAsync;
import org.iabako.shared.iservice.business.ServiceServiceAsync;
import org.iabako.shared.querydefinition.columndefinition.SaleColumnEnum;
import org.iabako.shared.querydefinition.dto.QueryOperatorEnum;
import org.iabako.shared.tools.GenericTools;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jose on 04/09/14.
 */
public class SaleSearchForm extends Composite {

    @UiTemplate("org.iabako.client.ui.form.business.SearchForm.ui.xml")
    interface SearchFormTemplate extends UiBinder<HTMLPanel, SearchForm> {
    }

    interface SaleSearchTemplate extends UiBinder<HTMLPanel, SaleSearchForm> {
    }

    private static final SearchFormTemplate binderSearchForm = GWT.create(SearchFormTemplate.class);
    private static final SaleSearchTemplate binderSaleSearchForm = GWT.create(SaleSearchTemplate.class);

    private final SaleServiceAsync saleServiceAsync = SaleServiceAsync.Util.getInstance();
    @UiField
    InputTextDate salesAfter;
    @UiField
    InputTextDate salesBefore;
    @UiField
    CheckboxBoolean showSalesOK;
    @UiField
    CheckboxBoolean showSalesInDebt;
    @UiField
    CheckboxBoolean showSalesDraft;
    @UiField
    CheckboxBoolean showSalesWithFutureInstallments;
    @UiField
    SelectList product;
    @UiField
    SelectList service;
    @UiField
    CustomFieldsInstance customFieldsInstance;
    @UiField
    InputTextDate paymentsAfter;
    @UiField
    InputTextDate paymentsBefore;
    @UiField
    InputTextDate installmentsAfter;
    @UiField
    InputTextDate installmentsBefore;
    @UiField
    HTMLPanel clientCategoriesPanel;
    @UiField
    HTMLPanel saleStatusCriteria;
    @UiField
    HTMLPanel quoteStatusCriteria;
    @UiField
    CheckboxBoolean showQuoteDraft;
    @UiField
    CheckboxBoolean showQuoteGenerated;
    @UiField
    CheckboxBoolean showQuoteTransformed;
    @UiField
    CheckboxBoolean showQuoteDiscarded;
    @UiField
    HTMLPanel paymentsInstallmentsCriteria;

    public SearchForm searchForm;
    public boolean quoteMode;
    SearchActionHandler searchActionHandler;

    public SaleSearchForm(DefaultSuggestHandler suggestServiceAsync, DataTable dataTable) {
        searchForm = new SearchForm() {
            @Override
            protected void addSpecificCriteria() {
                addSaleCriteria(quoteMode);
            }

            @Override
            protected void cleanSpecificCriteria() {
                cleanSaleCriteria();
            }
        };

        HTMLPanel searchFormPanel = binderSearchForm.createAndBindUi(searchForm);
        HTMLPanel saleSearchPanel = binderSaleSearchForm.createAndBindUi(this);

        searchForm.addToDisclosureFormPanelContent(saleSearchPanel);
        searchForm.setProperties(saleServiceAsync, suggestServiceAsync, dataTable, "search_motor_sale_principal_input_title");
        searchForm.showClientCustomFieldsCriteria(customFieldsInstance);
        searchForm.showClientCategoriesCriteria(clientCategoriesPanel);

        initialize();

        initWidget(searchFormPanel);

        setHandlers();
    }

    public void activateQuoteMode() {
        quoteMode = true;

        saleStatusCriteria.setVisible(false);
        paymentsInstallmentsCriteria.setVisible(false);
        quoteStatusCriteria.setVisible(true);
        setQuoteHandlers();
    }

    private void initialize() {
        initializeProducts();
        initializeServices();
    }

    private void initializeProducts() {
        if (GenericTools.isEmpty(service.getValues())) {
            ProductServiceAsync.Util.getInstance().getProducts(new IabakoAsyncCallback<List<Product>>() {
                public void onSuccess(List<Product> result) {
                    if (GenericTools.isEmpty(result)) {
                        super.onSuccess(result);
                        return;
                    }
                    Map<Long, String> products = new LinkedHashMap<Long, String>();
                    for (Product product : result) {
                        products.put(product.getId(), product.getName());
                    }
                    product.setValues(products);
                    product.sortValues();
                    super.onSuccess(result);
                }
            });
        }
    }

    private void initializeServices() {
        if (GenericTools.isEmpty(service.getValues())) {
            ServiceServiceAsync.Util.getInstance().getServices(new IabakoAsyncCallback<List<Service>>() {
                public void onSuccess(List<Service> result) {
                    if (GenericTools.isEmpty(result)) {
                        super.onSuccess(result);
                        return;
                    }
                    Map<Long, String> services = new LinkedHashMap<Long, String>();
                    for (Service service : result) {
                        services.put(service.getId(), service.getName());
                    }
                    service.setValues(services);
                    service.sortValues();
                    super.onSuccess(result);
                }
            });
        }
    }

    private void cleanSaleCriteria() {
        product.setRawValue(null);
        service.setRawValue(null);
        salesAfter.setValue(null);
        salesBefore.setValue(null);
        paymentsAfter.setValue(null);
        paymentsBefore.setValue(null);
        installmentsAfter.setValue(null);
        installmentsBefore.setValue(null);
        showSalesOK.setValue(false);
        showSalesInDebt.setValue(false);
        showSalesDraft.setValue(false);
        showSalesWithFutureInstallments.setValue(false);
        showQuoteDraft.setValue(false);
        showQuoteGenerated.setValue(false);
        showQuoteTransformed.setValue(false);
        showQuoteDiscarded.setValue(false);
    }

    private void setHandlers() {

        DOM.sinkEvents(showSalesOK.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showSalesInDebt.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showSalesDraft.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showSalesWithFutureInstallments.getCheckbox().getElement(), Event.MOUSEEVENTS);

        TooltipListener showSalesOKLabelListener = new TooltipListener(FinancialStatusSale._3_OK.getTitle());
        showSalesOK.getCheckbox().addHandler(showSalesOKLabelListener, MouseOverEvent.getType());
        showSalesOK.getCheckbox().addHandler(showSalesOKLabelListener, MouseOutEvent.getType());

        TooltipListener showSalesInDebtLabelListener = new TooltipListener(FinancialStatusSale._1_inDebt.getTitle());
        showSalesInDebt.getCheckbox().addHandler(showSalesInDebtLabelListener, MouseOverEvent.getType());
        showSalesInDebt.getCheckbox().addHandler(showSalesInDebtLabelListener, MouseOutEvent.getType());

        TooltipListener showSalesWithFutureInstallmentsLabelListener = new TooltipListener(FinancialStatusSale._2_withFutureInstallments.getTitle());
        showSalesWithFutureInstallments.getCheckbox().addHandler(showSalesWithFutureInstallmentsLabelListener, MouseOverEvent.getType());
        showSalesWithFutureInstallments.getCheckbox().addHandler(showSalesWithFutureInstallmentsLabelListener, MouseOutEvent.getType());

        TooltipListener showSalesDraftLabelListener = new TooltipListener(FinancialStatusSale._0_draft.getTitle());
        showSalesDraft.getCheckbox().addHandler(showSalesDraftLabelListener, MouseOverEvent.getType());
        showSalesDraft.getCheckbox().addHandler(showSalesDraftLabelListener, MouseOutEvent.getType());

        showSalesOK.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showSalesOK.getValue()) {
                    showSalesInDebt.setValue(false);
                    showSalesWithFutureInstallments.setValue(false);
                    showSalesDraft.setValue(false);
                }
            }
        });
        showSalesInDebt.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showSalesInDebt.getValue()) {
                    showSalesOK.setValue(false);
                    showSalesWithFutureInstallments.setValue(false);
                    showSalesDraft.setValue(false);
                }
            }
        });
        showSalesWithFutureInstallments.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showSalesWithFutureInstallments.getValue()) {
                    showSalesOK.setValue(false);
                    showSalesInDebt.setValue(false);
                    showSalesDraft.setValue(false);
                }
            }
        });
        showSalesDraft.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showSalesDraft.getValue()) {
                    showSalesOK.setValue(false);
                    showSalesWithFutureInstallments.setValue(false);
                    showSalesInDebt.setValue(false);
                }
            }
        });

        searchActionHandler = new SearchActionHandler(searchForm);

        product.getSelectField().addChangeHandler(searchActionHandler);
        service.getSelectField().addChangeHandler(searchActionHandler);

        salesAfter.getInputFieldDate().addValueChangeHandler(searchActionHandler);
        salesBefore.getInputFieldDate().addValueChangeHandler(searchActionHandler);
        paymentsAfter.getInputFieldDate().addValueChangeHandler(searchActionHandler);
        paymentsBefore.getInputFieldDate().addValueChangeHandler(searchActionHandler);
        installmentsAfter.getInputFieldDate().addValueChangeHandler(searchActionHandler);
        installmentsBefore.getInputFieldDate().addValueChangeHandler(searchActionHandler);

        showSalesOK.getCheckbox().addClickHandler(searchActionHandler);
        showSalesInDebt.getCheckbox().addClickHandler(searchActionHandler);
        showSalesDraft.getCheckbox().addClickHandler(searchActionHandler);
        showSalesWithFutureInstallments.getCheckbox().addClickHandler(searchActionHandler);
    }

    private void setQuoteHandlers() {

        DOM.sinkEvents(showQuoteDraft.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showQuoteGenerated.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showQuoteTransformed.getCheckbox().getElement(), Event.MOUSEEVENTS);
        DOM.sinkEvents(showQuoteDiscarded.getCheckbox().getElement(), Event.MOUSEEVENTS);

        TooltipListener showQuoteDraftListener = new TooltipListener(FinancialStatusSale._0_quote_draft.getTitle());
        showQuoteDraft.getCheckbox().addHandler(showQuoteDraftListener, MouseOverEvent.getType());
        showQuoteDraft.getCheckbox().addHandler(showQuoteDraftListener, MouseOutEvent.getType());

        TooltipListener showQuoteGeneratedLabelListener = new TooltipListener(FinancialStatusSale._1_quote_generated.getTitle());
        showQuoteGenerated.getCheckbox().addHandler(showQuoteGeneratedLabelListener, MouseOverEvent.getType());
        showQuoteGenerated.getCheckbox().addHandler(showQuoteGeneratedLabelListener, MouseOutEvent.getType());

        TooltipListener showQuoteTransformedListener = new TooltipListener(FinancialStatusSale._2_quote_transformed.getTitle());
        showQuoteTransformed.getCheckbox().addHandler(showQuoteTransformedListener, MouseOverEvent.getType());
        showQuoteTransformed.getCheckbox().addHandler(showQuoteTransformedListener, MouseOutEvent.getType());

        TooltipListener showQuoteDiscardedLabelListener = new TooltipListener(FinancialStatusSale._3_quote_discard.getTitle());
        showQuoteDiscarded.getCheckbox().addHandler(showQuoteDiscardedLabelListener, MouseOverEvent.getType());
        showQuoteDiscarded.getCheckbox().addHandler(showQuoteDiscardedLabelListener, MouseOutEvent.getType());

        showQuoteDraft.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showQuoteDraft.getValue()) {
                    showQuoteGenerated.setValue(false);
                    showQuoteTransformed.setValue(false);
                    showQuoteDiscarded.setValue(false);
                }
            }
        });
        showQuoteGenerated.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showQuoteGenerated.getValue()) {
                    showQuoteDraft.setValue(false);
                    showQuoteTransformed.setValue(false);
                    showQuoteDiscarded.setValue(false);
                }
            }
        });
        showQuoteTransformed.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showQuoteTransformed.getValue()) {
                    showQuoteDraft.setValue(false);
                    showQuoteGenerated.setValue(false);
                    showQuoteDiscarded.setValue(false);
                }
            }
        });
        showQuoteDiscarded.getCheckbox().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (showQuoteDiscarded.getValue()) {
                    showQuoteDraft.setValue(false);
                    showQuoteGenerated.setValue(false);
                    showQuoteTransformed.setValue(false);
                }
            }
        });

        showQuoteDraft.getCheckbox().addClickHandler(searchActionHandler);
        showQuoteGenerated.getCheckbox().addClickHandler(searchActionHandler);
        showQuoteTransformed.getCheckbox().addClickHandler(searchActionHandler);
        showQuoteDiscarded.getCheckbox().addClickHandler(searchActionHandler);
    }

    private void addSaleCriteria(boolean isQuote) {
        if (!GenericTools.isEmpty(product.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.productId, QueryOperatorEnum.IN, (Long) product.getValue());
        }
        if (!GenericTools.isEmpty(service.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.serviceId, QueryOperatorEnum.IN, (Long) service.getValue());
        }
        if (!GenericTools.isEmpty(salesAfter.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.date, QueryOperatorEnum.GREATER_THAN_OR_EQUALS, salesAfter.getDateValue());
        }
        if (!GenericTools.isEmpty(salesBefore.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.date, QueryOperatorEnum.LESS_THAN_OR_EQUALS, salesBefore.getDateValue());
        }
        if (!GenericTools.isEmpty(paymentsAfter.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.salePaymentsDate, QueryOperatorEnum.GREATER_THAN_OR_EQUALS, paymentsAfter.getDateValue());
        }
        if (!GenericTools.isEmpty(paymentsBefore.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.salePaymentsDate, QueryOperatorEnum.LESS_THAN_OR_EQUALS, paymentsBefore.getDateValue());
        }
        if (!GenericTools.isEmpty(installmentsAfter.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.saleInstallmentsDate, QueryOperatorEnum.GREATER_THAN_OR_EQUALS, installmentsAfter.getDateValue());
        }
        if (!GenericTools.isEmpty(installmentsBefore.getValue())) {
            searchForm.addCriteria(SaleColumnEnum.saleInstallmentsDate, QueryOperatorEnum.LESS_THAN_OR_EQUALS, installmentsBefore.getDateValue());
        }

        if (isQuote) {
            addQuoteStatusCriteria();
        } else {
            addSaleStatusCriteria();
        }
    }

    private void addSaleStatusCriteria() {
        if (showSalesOK.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._3_OK);
        }
        if (showSalesInDebt.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._1_inDebt);
        }
        if (showSalesDraft.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._0_draft);
        }
        if (showSalesWithFutureInstallments.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._2_withFutureInstallments);
        }
    }

    private void addQuoteStatusCriteria() {
        if (showQuoteDraft.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._0_quote_draft);
        }
        if (showQuoteGenerated.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._1_quote_generated);
        }
        if (showQuoteTransformed.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._2_quote_transformed);
        }
        if (showQuoteDiscarded.getValue()) {
            searchForm.addCriteria(SaleColumnEnum.status, QueryOperatorEnum.EQUALS, FinancialStatusSale._3_quote_discard);
        }
    }
}
